package com.foohoo.benchmark.string;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.util.concurrent.TimeUnit;

/**
 * 测试底层为数组方式实现的工具类(StringBuilder)不指定大小对性能的影响
 * Benchmark                                    Mode  Cnt   Score    Error  Units
 * StringBuilderInitialSize.withInitialSize     avgt    3  17.513 ± 22.465  ms/op
 * StringBuilderInitialSize.withoutInitialSize  avgt    3  20.607 ± 21.814  ms/op
 * 一句话结论: 合理指定了初始大小的StringBuilder扩容次数更少，可以节省扩容时旧数组复制到新数组的时间
 * 注: StringBuffer同理
 *
 * @author mzdbxqh
 * @date 2020-10-26 11:57
 **/
@Slf4j
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(1)
@Threads(1)
@State(Scope.Benchmark)
public class StringBuilderInitialSize {

	private static final String FILL_STRING = "12345678";

	private static final int LOOP_SIZE = 1024 * 1024;

	@Benchmark
	public void withInitialSize(Blackhole bh) {
		StringBuilder builder = new StringBuilder(FILL_STRING.length() * LOOP_SIZE);
		for (int i = 0; i < LOOP_SIZE; i++) {
			builder.append(FILL_STRING);
		}
		bh.consume(builder.toString());
	}

	@Benchmark
	public void withoutInitialSize(Blackhole bh) {
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < LOOP_SIZE; i++) {
			builder.append(FILL_STRING);
		}
		bh.consume(builder.toString());
	}
}
